package db_meta

import (
	"time"

	"gitee.com/ameise84/e3utils/str_conv"
	"github.com/rs/xid"
	"servers/models/define"
	"servers/models/protos/google/pb/rpc_protos"
	"servers/utils"
)

type LogMeta interface {
	BaseTableName() string
	TableName() string
}

type DotCtrlLog struct {
	LogID      string                `json:"log_id" form:"log_id" gorm:"column:primarykey;log_id"`
	UserID     uint64                `json:"user_id" form:"user_id" gorm:"column:user_id"`
	Account    string                `json:"account" form:"account" gorm:"column:account"`
	BusinessID define.BusinessIDType `json:"bid" form:"bid" gorm:"column:bid"`
	ScoreType  define.ScoreType      `json:"score_type" form:"score_type" gorm:"column:score_type"`
	Before     string                `json:"before" form:"before" gorm:"column:before"`
	After      string                `json:"after" form:"after" gorm:"column:after"`
	OpFrom     int32                 `json:"op_from" form:"op_from" gorm:"column:op_from"`
	OpID       string                `json:"op_id" form:"op_id" gorm:"column:op_id"`
	RecordTime int64                 `json:"record_time" form:"record_time" gorm:"column:record_time;index:idx_record_time"`
}

func (v *DotCtrlLog) Take() LogMeta {
	return &DotCtrlLog{}
}

func (v *DotCtrlLog) BaseTableName() string {
	return "log_dot_ctrl"
}

func (v *DotCtrlLog) TableName() string {
	return v.BaseTableName()
}

func (v *DotCtrlLog) FromPB(msg *rpc_protos.DotCtrlLog) {
	v.LogID = xid.New().String()
	v.UserID = msg.UserID
	v.Account = msg.Account
	v.BusinessID = msg.BusinessID
	v.ScoreType = msg.ScoreType
	v.Before = msg.Before
	v.After = msg.After
	v.OpFrom = msg.OpFrom
	v.OpID = msg.OpID
	v.RecordTime = msg.RecordTime
}

type PlayerUseBankLog struct {
	LogID       string                `json:"log_id" form:"log_id" gorm:"primarykey;column:log_id"`
	Order       string                `json:"order" form:"order" gorm:"column:order"`
	UserID      define.UserIDType     `json:"user_id" form:"user_id" gorm:"column:user_id;index:idx_uid"`
	Account     string                `json:"account" form:"account" gorm:"column:account"`
	BusinessID  define.BusinessIDType `json:"bid" form:"bid" gorm:"column:bid"`
	ScoreType   define.ScoreType      `json:"score_type" form:"score_type" gorm:"column:score_type"`
	BeforeScore define.GameScore      `json:"before_score" form:"before_score" gorm:"column:before_score"`
	AfterScore  define.GameScore      `json:"after_score" form:"after_score" gorm:"column:after_score"`
	ChangeScore define.GameScore      `json:"change_score" form:"change_score" gorm:"column:change_score"`
	RecordTime  int64                 `json:"record_time" form:"record_time" gorm:"column:record_time;index:idx_record_time"`
}

func (v *PlayerUseBankLog) BaseTableName() string {
	return "log_use_bank"
}

func (v *PlayerUseBankLog) TableName() string {
	return v.BaseTableName()
}

func (v *PlayerUseBankLog) FromPB(msg *rpc_protos.PlayerUseBankLog) {
	v.LogID = xid.New().String()
	v.Order = msg.Order
	v.UserID = msg.UserID
	v.Account = msg.Account
	v.BusinessID = msg.BusinessID
	v.ScoreType = msg.ScoreType
	v.BeforeScore = msg.BeforeScore
	v.AfterScore = msg.AfterScore
	v.ChangeScore = msg.ChangeScore
	v.RecordTime = msg.RecordTime
}

type GameRecordLog struct {
	LogID       string                `json:"log_id" form:"log_id" gorm:"primarykey;column:log_id"`
	UserID      define.UserIDType     `json:"user_id" form:"user_id" gorm:"column:user_id;index:idx_user_id"`
	Account     string                `json:"account" form:"account" gorm:"column:account"`
	BusinessID  define.BusinessIDType `json:"bid" form:"bid" gorm:"column:bid;index:idx_bid"`
	ScoreType   define.ScoreType      `json:"score_type" form:"score_type" gorm:"column:score_type;index:idx_score_type"`
	GameKindID  define.GameKind       `json:"game_kind" form:"game_kind" gorm:"column:game_kind;index:idx_game_kind"`
	JackpotID   uint32                `json:"jackpot_id" form:"jackpot_id" gorm:"column:jackpot_id"`
	ScoreBefore define.GameScore      `json:"score_before" form:"score_before" gorm:"column:score_before"`
	ScoreAfter  define.GameScore      `json:"score_after" form:"score_after" gorm:"column:score_after"`
	Round       uint64                `json:"round" form:"round" gorm:"column:round"`
	SubRound    uint64                `json:"sub_round" form:"sub_round" gorm:"column:sub_round"`
	EndRound    bool                  `json:"end_round" form:"end_round" gorm:"column:end_round"`
	BetKind     int32                 `json:"bet_kind" form:"bet_kind" gorm:"column:bet_kind"`
	ScoreBet    define.GameScore      `json:"score_bet" form:"score_bet" gorm:"column:score_bet"`
	ScoreCost   define.GameScore      `json:"score_cost" form:"score_cost" gorm:"column:score_cost"`
	ScoreReward define.GameScore      `json:"score_reward" form:"score_reward" gorm:"column:score_reward"`
	GameFlag    int64                 `json:"game_flag" form:"game_flag" gorm:"column:game_flag"`
	GameData    []byte                `json:"game_data" form:"game_data" gorm:"column:game_data"`
	RecordTime  int64                 `json:"record_time" form:"record_time" gorm:"column:record_time;index:idx_record_time"`
}

func (v *GameRecordLog) BaseTableName() string {
	return "log_game_record_"
}

func (v *GameRecordLog) TableName() string {
	t := time.Unix(v.RecordTime, 0).UTC()
	return utils.GetMonthTableName(v.BaseTableName(), t) // 根据RecordTime分表
}

func (v *GameRecordLog) FromPB(msg *rpc_protos.GameRecordLog) {
	v.LogID = msg.Info.LogID
	v.UserID = msg.UserID
	v.Account = msg.Account
	v.BusinessID = msg.BusinessID
	v.ScoreType = msg.ScoreType
	v.GameKindID = msg.GameKindID
	v.JackpotID = msg.Result.JackpotID
	v.ScoreBefore = msg.Result.ScoreBefore
	v.ScoreAfter = msg.Result.ScoreAfter
	v.Round = msg.Round
	v.SubRound = msg.SubRound
	v.EndRound = msg.Info.EndRound
	v.BetKind = msg.Info.BetKind
	v.ScoreBet = msg.Info.BetScore
	v.ScoreCost = msg.Info.CostScore
	v.ScoreReward = msg.Info.RewardScore
	v.GameFlag = msg.Info.GameFlag
	v.GameData = msg.GameData
	v.RecordTime = msg.Info.Timestamp
}

func (v *GameRecordLog) WhereGame() string {
	return "game_kind = ?"
}

func (v *GameRecordLog) WherePlayer() string {
	return "user_id = ?"
}

func (v *GameRecordLog) WhereRecordBetween() string {
	return "record_time >= ? AND record_time < ?"
}

func (v *GameRecordLog) WhereLogID() string {
	return "log_id = ?"
}

type LoginLogoutLog struct {
	LogID       string                `json:"log_id" form:"log_id" gorm:"primarykey;column:log_id"`
	UserID      define.UserIDType     `json:"user_id" form:"user_id" gorm:"column:user_id"`
	Account     string                `json:"account" form:"account" gorm:"column:account"`
	BusinessID  define.BusinessIDType `json:"bid" form:"bid" gorm:"column:bid"`
	ScoreType   define.ScoreType      `json:"score_type" form:"score_type" gorm:"column:score_type"`
	GameKindID  define.GameKind       `json:"game_kind" form:"game_kind" gorm:"column:game_kind"`
	LoginScore  define.GameScore      `json:"login_score" form:"login_score" gorm:"column:login_score"`
	LoginTime   int64                 `json:"login_time" form:"login_time" gorm:"column:login_time;index:idx_in_time"`
	LoginIP     string                `json:"login_ip" form:"login_ip" gorm:"column:login_ip"`
	LogoutScore define.GameScore      `json:"logout_score" form:"logout_score" gorm:"column:logout_score"`
	LogoutTime  int64                 `json:"logout_time" form:"logout_time" gorm:"column:logout_time;index:idx_out_time"`
	LogoutIP    string                `json:"logout_ip" form:"logout_ip" gorm:"column:logout_ip"`
	Seconds     int64                 `json:"seconds" form:"seconds" gorm:"column:seconds"`
}

func (v *LoginLogoutLog) BaseTableName() string {
	return "log_login_logout"
}

func (v *LoginLogoutLog) TableName() string {
	// t := time.Unix(v.LogoutTime, 0)
	// key := fmt.Sprintf("%4d%2d", t.Year(), t.Month())
	return v.BaseTableName()
}

func (v *LoginLogoutLog) FromPB(msg *rpc_protos.LoginLogoutLog) {
	v.LogID = xid.New().String()
	v.UserID = msg.UserID
	v.Account = msg.Account
	v.BusinessID = msg.BusinessID
	v.ScoreType = msg.ScoreType
	v.GameKindID = msg.GameKindID
	v.LoginScore = msg.LoginScore
	v.LoginTime = msg.LoginTime
	v.LoginIP = msg.LoginIP
	v.LogoutScore = msg.LogoutScore
	v.LogoutTime = msg.LogoutTime
	v.LogoutIP = msg.LogoutIP
	v.Seconds = msg.Seconds
}

type ActiveUserIDsReport struct {
	BusinessID define.BusinessIDType `json:"bid" form:"bid" gorm:"primarykey;column:bid"`
	GameKindID define.GameKind       `json:"game_kind" form:"game_kind" gorm:"primarykey;column:game_kind"`
	RecordTime int64                 `json:"record_time" form:"record_time" gorm:"primarykey;column:record_time"`

	NewLoginIDs    []byte `json:"new_login_i_ds" form:"new_login_i_ds" gorm:"column:new_login_i_ds"`
	NewBetIDs      []byte `json:"new_bet_i_ds" form:"new_bet_i_ds" gorm:"column:new_bet_i_ds"`
	ActiveLoginIDs []byte `json:"active_login_i_ds" form:"active_login_i_ds" gorm:"column:active_login_i_ds"`
	ActiveBetIDs   []byte `json:"active_bet_i_ds" form:"active_bet_i_ds" gorm:"column:active_bet_i_ds"`
}

func (v *ActiveUserIDsReport) BaseTableName() string {
	return v.TableName()
}

func (v *ActiveUserIDsReport) TableName() string {
	return "report_active_user_ids"
}

func (v *ActiveUserIDsReport) SelectAny() []string {
	return []string{"bid", "game_kind", "record_time", "new_count", "new_count_valid", "active_count", "max_online_count"}
}

func (v *ActiveUserIDsReport) WhereRecordTime() string {
	return "record_time = ?"
}

type OnlineUsersReport struct {
	LogID          uint64                `json:"id" form:"id" gorm:"primarykey;column:id"`
	BusinessID     define.BusinessIDType `json:"bid" form:"bid" gorm:"column:bid"`
	GameKindID     define.GameKind       `json:"game_kind" form:"game_kind" gorm:"column:game_kind"`
	RecordTime     int64                 `json:"record_time" form:"record_time" gorm:"column:record_time;index:idx_time"`
	OnlineCount    int64                 `json:"online_count" form:"online_count" gorm:"column:online_count"`
	MaxOnlineCount int64                 `json:"max_online_count" form:"max_online_count" gorm:"column:max_online_count"`
}

func (v *OnlineUsersReport) BaseTableName() string {
	return v.TableName()
}

func (v *OnlineUsersReport) TableName() string {
	return "report_online_users"
}

type ActiveUserReport struct {
	BusinessID       define.BusinessIDType `json:"bid" form:"bid" gorm:"primarykey;column:bid;"`
	GameKindID       *define.GameKind      `json:"game_kind" form:"game_kind" gorm:"primarykey;column:game_kind"`
	RecordTime       int64                 `json:"record_time" form:"record_time" gorm:"primarykey;column:record_time"`
	MaxOnlineCount   int64                 `json:"max_online_count" form:"max_online_count" gorm:"column:max_online_count"`
	NewLoginCount    int64                 `json:"new_login_count" form:"new_login_count" gorm:"column:new_login_count"`
	NewBetCount      int64                 `json:"new_bet_count" form:"new_bet_count" gorm:"column:new_bet_count"`
	ActiveLoginCount int64                 `json:"active_login_count" form:"active_login_count" gorm:"column:active_login_count"`
	ActiveBetCount   int64                 `json:"active_bet_count" form:"active_bet_count" gorm:"column:active_bet_count"`
	RetentionLogin2  int64                 `json:"retention_login2" form:"retention_login2" gorm:"column:retention_login2"`
	RetentionLogin3  int64                 `json:"retention_login3" form:"retention_login3" gorm:"column:retention_login3"`
	RetentionLogin7  int64                 `json:"retention_login7" form:"retention_login7" gorm:"column:retention_login7"`
	RetentionLogin15 int64                 `json:"retention_login15" form:"retention_login15" gorm:"column:retention_login15"`
	RetentionLogin30 int64                 `json:"retention_login30" form:"retention_login30" gorm:"column:retention_login30"`
	RetentionBet2    int64                 `json:"retention_bet2" form:"retention_bet2" gorm:"column:retention_bet2"`
	RetentionBet3    int64                 `json:"retention_bet3" form:"retention_bet3" gorm:"column:retention_bet3"`
	RetentionBet7    int64                 `json:"retention_bet7" form:"retention_bet7" gorm:"column:retention_bet7"`
	RetentionBet15   int64                 `json:"retention_bet15" form:"retention_bet15" gorm:"column:retention_bet15"`
	RetentionBet30   int64                 `json:"retention_bet30" form:"retention_bet30" gorm:"column:retention_bet30"`
}

func (v *ActiveUserReport) TableName() string {
	return "report_active_users"
}

type GameJackpotReport struct {
	JackpotID     uint32                `json:"jackpot_id" form:"jackpot_id" gorm:"column:jackpot_id;index:idx_jid"`
	GameKindID    define.GameKind       `json:"game_kind" form:"game_kind" gorm:"column:game_kind"`
	IndexTag      uint32                `json:"index_tag" form:"index_tag" gorm:"column:index_tag"`
	BusinessID    define.BusinessIDType `json:"bid" form:"bid" gorm:"column:bid"`
	ScoreType     define.ScoreType      `json:"score_type" form:"score_type" gorm:"column:score_type"`
	TotalInScore  define.GameScore      `json:"total_in_score" form:"total_in_score" gorm:"column:total_in_score"`
	TotalOutScore define.GameScore      `json:"total_out_score" form:"total_out_score" gorm:"column:total_out_score"`
	TodayInScore  define.GameScore      `json:"today_in_score" form:"today_in_score" gorm:"column:today_in_score"`
	TodayOutScore define.GameScore      `json:"today_out_score" form:"today_out_score" gorm:"column:today_out_score"`
	RecordTime    int64                 `json:"record_time" form:"record_time" gorm:"column:record_time;index:idx_time"`
}

func (v *GameJackpotReport) BaseTableName() string {
	return "report_game_jackpot"
}

func (v *GameJackpotReport) TableName() string {
	return v.BaseTableName()
}

func (v *GameJackpotReport) FromPB(msg *rpc_protos.GameJackpotReport) {
	v.JackpotID = msg.JackpotID
	v.GameKindID = msg.GameKindID
	v.IndexTag = msg.IndexTag
	v.BusinessID = msg.BusinessID
	v.ScoreType = msg.ScoreType
	v.TotalInScore = msg.TotalInScore
	v.TotalOutScore = msg.TotalOutScore
	v.TodayInScore = msg.TodayInScore
	v.TodayOutScore = msg.TodayOutScore
	v.RecordTime = msg.RecordTime
}

type PlayerBetInGameReport struct {
	GameKindID define.GameKind `json:"game_kind" form:"game_kind" gorm:"column:game_kind"`
	PlayerBetReport
}

func (v *PlayerBetInGameReport) BaseTableName() string {
	return "report_player_bet_in_"
}

func (v *PlayerBetInGameReport) TableName() string {
	return v.BaseTableName() + str_conv.ToString(v.GameKindID)
}

func (v *PlayerBetInGameReport) FromPB(msg *rpc_protos.PlayerBetInGameReport) {
	v.UserID = msg.UserID
	v.Account = msg.Account
	v.BusinessID = msg.BusinessID
	v.ScoreType = msg.ScoreType
	v.GameKindID = msg.GameKindID
	v.TotalBetScore = msg.TotalBetScore
	v.TotalRewardScore = msg.TotalRewardScore
	v.TotalRound = msg.TotalRound
	v.TodayBetScore = msg.TodayBetScore
	v.TodayRewardScore = msg.TodayRewardScore
	v.TodayRound = msg.TodayRound
	v.RecordTime = msg.RecordTime
}

type PlayerBetReport struct {
	UserID           uint64                `json:"user_id" form:"user_id" gorm:"column:user_id;index:idx_uid"`
	Account          string                `json:"account" form:"account" gorm:"column:account"`
	BusinessID       define.BusinessIDType `json:"bid" form:"bid" gorm:"column:bid"`
	ScoreType        define.ScoreType      `json:"score_type" form:"score_type" gorm:"column:score_type"`
	TotalBetScore    define.GameScore      `json:"total_bet_score" form:"total_bet_score" gorm:"column:total_bet_score"`
	TotalRewardScore define.GameScore      `json:"total_reward_score" form:"total_reward_score" gorm:"column:total_reward_score"`
	TotalRound       int64                 `json:"total_round" form:"total_round" gorm:"column:total_round"`
	TodayBetScore    define.GameScore      `json:"today_bet_score" form:"today_bet_score" gorm:"column:today_bet_score"`
	TodayRewardScore define.GameScore      `json:"today_reward_score" form:"today_reward_score" gorm:"column:today_reward_score"`
	TodayRound       int64                 `json:"today_round" form:"today_round" gorm:"column:today_round"`
	RecordTime       int64                 `json:"record_time" form:"record_time" gorm:"column:record_time;index:idx_time"`
}

func (v *PlayerBetReport) BaseTableName() string {
	return "report_player_bet"
}

func (v *PlayerBetReport) TableName() string {
	return v.BaseTableName()
}

func (v *PlayerBetReport) FromPB(msg *rpc_protos.PlayerBetReport) {
	v.UserID = msg.UserID
	v.Account = msg.Account
	v.BusinessID = msg.BusinessID
	v.ScoreType = msg.ScoreType
	v.TotalBetScore = msg.TotalBetScore
	v.TotalRewardScore = msg.TotalRewardScore
	v.TotalRound = msg.TotalRound
	v.TodayBetScore = msg.TodayBetScore
	v.TodayRewardScore = msg.TodayRewardScore
	v.TodayRound = msg.TodayRound
	v.RecordTime = msg.RecordTime
}
